#ifndef NETLIB_SOCKETSOPS_H
#define NETLIB_SOCKETSOPS_H

// socket相关的系统调用封装

#include <arpa/inet.h>

namespace netlib
{

namespace net
{

namespace sockets
{

// 创建一个非阻塞套接字
int createNonblockingOrDie(sa_family_t family);

// 主动发起连接
int connect(int sockfd, const struct sockaddr* addr);

// IP、端口号与套接字绑定
void bindOrDie(int sockfd, const struct sockaddr* addr);

// 开启监听套接字
void listenOrDie(int sockfd);

// 接受连接分配fd
int accept(int sockfd, struct sockaddr_in6* addr);

// 从套接字中读取数据
ssize_t read(int sockfd, void *buf, size_t count);

// 从描述符中读取数据到分散的内存块
ssize_t readv(int sockfd, const struct iovec *iov, int iovcnt);

// 向套接字中写入数据
ssize_t write(int sockfd, const void *buf, size_t count);

// 关闭套接字
void close(int sockfd);

// 只关闭套接字写的一半
void shutdownWrite(int sockfd);

// 将IP以及端口信息转化成字符串
void toIpPort(char* buf, size_t size, const struct sockaddr* addr);

// 将IP信息转化成字符串
void toIp(char* buf, size_t size, const struct sockaddr* addr);

// 将字符串的IP和端口绑定到sockaddr_in IPv4结构体上
void fromIpPort(const char* ip, uint16_t port, struct sockaddr_in* addr);

// 将字符串的IP和端口绑定到sockaddr_in IPv6结构体上
void fromIpPort(const char* ip, uint16_t port, struct sockaddr_in6* addr);

// 获得sockfd错误码
int getSocketError(int sockfd);

// IPV4地址结构体指针转成通用的const socket结构体指针
const struct sockaddr* sockaddr_cast(const struct sockaddr_in* addr);

// IPV6地址结构体指针转成通用的const socket结构体指针
const struct sockaddr* sockaddr_cast(const struct sockaddr_in6* addr);

// IPV6地址结构体指针转成通用的socket结构体指针
struct sockaddr* sockaddr_cast(struct sockaddr_in6* addr);

// 通用的socket结构体指针转成const IPv4结构体指针
const struct sockaddr_in* sockaddr_in_cast(const struct sockaddr* addr);

// 通用的socket结构体指针转成const IPv6结构体指针
const struct sockaddr_in6* sockaddr_in6_cast(const struct sockaddr* addr);

// 获取套接字本地的sockaddr_in6 IPV6地址
struct sockaddr_in6 getLocalAddr(int sockfd);

// 获取套接字对端的sockaddr_in6 IPV6地址
struct sockaddr_in6 getPeerAddr(int sockfd);

bool isSelfConnect(int sockfd);

} // namespace sockets end

} // namespace net end

} // namespace netlib end

#endif